import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_draw/p19/particle.dart';
import 'package:flutter_draw/p19/particle_manage.dart';

class ImageWorld extends StatefulWidget {
  final Size size;

  const ImageWorld({super.key, required this.size});

  @override
  State<ImageWorld> createState() => _ImageWorldState();
}

/// 图片粒子背景效果
class _ImageWorldState extends State<ImageWorld>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  ParticleManage pm = ParticleManage();
  Random random = Random();

  @override
  void initState() {
    super.initState();
    loadImageFromAssets("assets/images/rain.png");
    pm.size = widget.size;
    initParticleManage();
    _controller =
        AnimationController(vsync: this, duration: const Duration(seconds: 1))
          ..addListener(pm.tick)
          ..repeat();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  //读取 assets 中的图片
  void loadImageFromAssets(String path) async {
    ByteData data = await rootBundle.load(path);
    pm.setImage(await decodeImageFromList(data.buffer.asUint8List()));
  }

  void initParticleManage() async {
    for (int i = 0; i < 60; i++) {
      Particle particle = Particle(
          x: pm.size.width / 60 * i,
          y: 0,
          vx: 1 * random.nextDouble() * pow(-1, random.nextInt(20)),
          vy: 4 * random.nextDouble() + 1);
      pm.particles.add(particle);
    }
  }

  void theWorld() {
    if (_controller.isAnimating) {
      _controller.stop();
    } else {
      _controller.repeat();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        SizedBox(
            width: widget.size.width,
            height: widget.size.height,
            child: Image.asset(
              'assets/images/bg.jpg',
              fit: BoxFit.cover,
            )),
        GestureDetector(
          onTap: theWorld,
          child: CustomPaint(
            size: pm.size,
            painter: WorldRender(
              manage: pm,
            ),
          ),
        ),
      ],
    );
  }
}

class WorldRender extends CustomPainter {
  final ParticleManage manage;

  WorldRender({required this.manage}) : super(repaint: manage);

  Paint fillPaint = Paint()
    ..colorFilter = const ColorFilter.matrix(<double>[
      1,
      0,
      0,
      0,
      0,
      0,
      1,
      0,
      0,
      0,
      0,
      0,
      1,
      0,
      0,
      0,
      0,
      0,
      0.4,
      0,
    ]);

  Paint stokePaint = Paint()
    ..strokeWidth = 0.5
    ..style = PaintingStyle.stroke;

  @override
  void paint(Canvas canvas, Size size) {
    if (manage.image == null) return;
    for (var particle in manage.particles) {
      drawParticle(canvas, particle);
    }
  }

  void drawParticle(Canvas canvas, Particle particle) {
    fillPaint.color = particle.color;
    if (manage.image == null) return;
    canvas.save();
    canvas.translate(particle.x, particle.y);
    var dis = sqrt(particle.vy * particle.vy + particle.vx * particle.vx);
    canvas.rotate(acos(particle.vx / dis) + pi + pi / 2);
    canvas.drawImageRect(
        manage.image!,
        Rect.fromLTWH(
            0, 0, manage.image!.width * 1.0, manage.image!.height * 1.0),
        Rect.fromLTWH(
            0, 0, manage.image!.width * 0.18, manage.image!.height * 0.18),
        fillPaint);
    canvas.restore();
  }

  @override
  bool shouldRepaint(covariant WorldRender oldDelegate) =>
      oldDelegate.manage != manage;
}
